home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / multidef.arc / MULTIDEF.C
Text File  |  1987-04-13  |  19KB  |  471 lines

  1. /*
  2. ** multidef.c - A program to scan a collection of .o and library files
  3. **              and search for multiply defined symbols.
  4. **              This can catch problems where a symbol is defined in your
  5. **              routine as well as in a scanned library (for example you
  6. **              have a roued executables have hunks
  7. **              in them that this program doesn't understand, besides the
  8. **              symbol information is gone from an executable anyway.
  9. **
  10. **      Copyright (c) 1886, Paul Jatkowski.
  11. */
  12. #include <stdio.h>
  13. #include <fcntl.h>
  14.  
  15. /* defines for the different hunk types */
  16.  
  17. #define HUNK_UNIT       0x3e7   /* start of a program unit */
  18. #define HUNK_NAME       0x3e8   /* name of hunk (optional) */
  19. #define HUNK_CODE       0x3e9   /* block of code, possibly to be relocated */
  20. #define HUNK_DATA       0x3ea   /* block of initialized data, possibly relocated */
  21. #define HUNK_BSS        0x3eb   /* uninitialized data */
  22. #define HUNK_RELOC32    0x3ec   /* 32 bit relocation entries */
  23. #define HUNK_RELOC16    0x3ed   /* 16 bit pc relative relocation entries */
  24. #define HUNK_RELOC8     0x3ee   /*  8 bit pc relative relocation entries */
  25. #define HUNK_EXT        0x3ef   /* external symbol info  ... see below */
  26. #define HUNK_SYMBOL     0x3f0   /* symbol table info, optional, for debuggers */
  27. #define HUNK_DEBUG      0x3f1   /* further debugging info */
  28. #define HUNK_END        0x3f2   /* end of a hunk */
  29. /* lattice 3.1 hunk types */
  30. #define HUNK_DRELOC32   0x3f7   /* 32 bit data section relative relocation */
  31. #define HUNK_DRELOC16   0x3f8   /* 16 bit data section relative relocation */
  32. #define HUNK_DRELOC8    0x3f9   /*  8 bit data section relative relocation */
  33.  
  34. /* the following hunk defines are for load files */
  35. #define HUNK_HEADER     0x3f3   /* info for loader ... lots of stuff in here */
  36. #define HUNK_OVERLAY    0x3f5   /* overlay table for overlay programs */
  37. #define HUNK_BREAK      0x3f6   /* end of overlay node */
  38.  
  39.  
  40. /* defines for HUNK_EXT hunk
  41. ** These are the important ones for getting symbol define/reference info
  42. */
  43.  
  44. #define EXT_SYMB        0               /* symbol table */
  45. #define EXT_DEF         1               /* relocatable definition */
  46. #define EXT_ABS         2               /* absolute definition */
  47. #define EXT_RES         3               /* resident library definition */
  48. #define EXT_REF32       129             /* 32 bit reference to symbol */
  49. #define EXT_COMMON      130             /* 32 bit reference to COMMON */
  50. #define EXT_REF16       131             /* 16 bit reference to symbol */
  51. #define EXT_REF8        132             /*  8 bit reference to symbol */
  52. /* lattice 3.1 extra defines */
  53. #define EXT_DREF32      133             /* 32 bit base relative to symbol */
  54. #define EXT_DREF16      134             /* 16 bit base relative to symbol */
  55. #define EXT_DREF8       135             /*  8 bit base relative to symbol */
  56.  
  57.  
  58. #define MAXBUF 100      /* buffer for "get_and_flush" and "myread" */
  59. long    buf[MAXBUF];
  60.  
  61. /* operation flags */
  62. int     pr_def = 0;     /* print symbol definition listing */
  63. int     pr_ref = 0;     /* print symbol reference  listing */
  64.  
  65. /* defines for t_insert routine (binary tree) */
  66. struct t_node {
  67.         struct  tnode   *right;
  68.         struct  tnode   *left;
  69.         char    *key;           /* symbol name */
  70.         char    *aux1;          /* file   name */
  71.         char    *aux2;          /* module name */
  72. };
  73. typedef struct t_node T_node;
  74.  
  75. /* declarations for forward referenced routines */
  76. T_node  *t_insert();
  77. void    save_def();
  78.  
  79. void
  80. myread(fd,ptr,sz)
  81. int     fd,sz;
  82. char    *ptr;
  83. {
  84.         if (read(fd,ptr,sz) != sz)
  85.         {
  86.                 printf("short read: aborting\n");
  87.                 exit(10);
  88.         }
  89. }
  90.  
  91. /* read n LONGS from the object file, used to flush unnecessary sections.
  92. ** I suppose that a seek would work also...... */
  93. void
  94. get_and_flush(objfile,n)
  95. int     objfile,n;
  96. {
  97.         int     n1;
  98.         n *= 4;
  99.         while (n > 0)
  100.         {
  101.                 n1 = n > MAXBUF ? MAXBUF : n;
  102.                 n -= n1;
  103.                 myread(objfile,buf,n1);
  104.         }
  105. }
  106. /*
  107. ** given a object or library file name, read it and find symbol entries.
  108. ** print references or definitions if the flags are set. Collect the
  109. ** to look for multiple defines
  110. */
  111. void
  112. procfile(fname)
  113. char    *fname;
  114. {
  115.         int     moretodo = 1;   
  116.         long    d1 = -1 ,d2;
  117.         int     ext_type;
  118.         char    curhunk[100];
  119.         char    curname[100];
  120.         int     hunkend = 0;
  121.         int     objfile;
  122.  
  123.         if (pr_def || pr_ref)
  124.                 printf("\t=========== processing %s ============\n",fname);
  125.                 
  126.         if ( (objfile = open(fname,O_RDONLY)) < 0)
  127.         {
  128.                 perror("can't open input file");
  129.                 poserr("amiga error");
  130.                 return;
  131.         }
  132.         
  133.         while (moretodo)
  134.         {
  135.                 /* read what is hopefully a hunk type */
  136.                 if (read(objfile,(char *)&d1,sizeof(d1)) != sizeof(d1))
  137.                 {
  138.                         if (!hunkend)
  139.                                 printf("Unexpected end of file! (no hunk end)\n");
  140.                         moretodo = 0;
  141.                         continue;
  142.                 }
  143.                 hunkend = 0;
  144.                 switch(d1)
  145.                 {
  146.                 case HUNK_UNIT:         /* 3e7  Start of program unit */
  147.                         myread(objfile,&d1,sizeof(d1));
  148.                         myread(objfile,buf,d1*4);
  149.                         buf[d1] = 0;
  150.                         strcpy(curhunk,(char *)buf);
  151. #ifdef DEBUG
  152.                         printf("hunk unit: %s\n",curhunk);
  153. #endif
  154.                         break;
  155.                                                                 
  156.                 case HUNK_NAME:         /* 3e8  Name of a hunk */
  157.                         myread(objfile,&d1,sizeof(d1));
  158.                         myread(objfile,buf,d1*4);
  159.                         buf[d1] = 0;
  160.                         strcpy(curname,(char *)buf);
  161. #ifdef DEBUG
  162.                         printf("hunk name: %s\n",curname);
  163. #endif
  164.                         break;
  165.  
  166.                 case HUNK_CODE:         /* 3e9  Code segment */
  167.                 case HUNK_DATA:         /* 3ea  Initialized Data segment */
  168.                         myread(objfile,&d1,sizeof(d1));
  169. #ifdef DEBUG
  170.                         printf("code/data hunk length=%d\n",d1);
  171. #endif  
  172.                         get_and_flush(objfile,d1);
  173.                         break;
  174.  
  175.                 case HUNK_BSS:          /* 3eb  Unitialized Data segment */
  176.                         myread(objfile,&d1,sizeof(d1));
  177. #ifdef DEBUG
  178.                         printf("bss section length=%d\n",d1);
  179. #endif
  180.                         break;                  
  181.  
  182.                 case HUNK_RELOC32:      /* 3ec  32-bit relocation list */
  183.                 case HUNK_RELOC16:      /* 3ed  16-bit PC-relative relocation info */
  184.                 case HUNK_RELOC8:       /* 3ee  8-bit PC-relative relocation info */
  185.                 case HUNK_DRELOC32:
  186.                 case HUNK_DRELOC16:
  187.                 case HUNK_DRELOC8:
  188. #ifdef DEBUG
  189.                         printf("reloc hunk type 0x%x\n",d1);
  190. #endif
  191.                         myread(objfile,&d1,sizeof(d1));
  192.                         while (d1 != 0)
  193.                         {
  194.                                 myread(objfile,&d2,sizeof(d2));
  195.                                 get_and_flush(objfile,d1);
  196.                                 myread(objfile,&d1,sizeof(d1));
  197.                         }
  198.                         break;
  199.                                                         
  200.                 case HUNK_EXT:          /* 3ef  External symbol info */
  201. #ifdef DEBUG
  202.                         printf("hunk ext\n");
  203. #endif
  204.                         myread(objfile,&d1,sizeof(d1));
  205.                         while (d1 != 0)
  206.                         {
  207.                                 ext_type = (d1 >> 24) & 0xff;
  208.                                 d1 &= 0xffffff;
  209.                                 switch(ext_type)
  210.                                 {
  211.                                 case EXT_SYMB:  /* symbol table */
  212.                                         get_and_flush(objfile,d1+1);
  213.                                         break;
  214.                                 case EXT_DEF:   /* reloc def */
  215.                                 case EXT_ABS:   /* abs def */
  216.                                 case EXT_RES:   /* resident lib */
  217.                                         myread(objfile,buf,d1*4);
  218.                                         buf[d1] = 0;
  219.                                         if (pr_def)
  220.                                                 printf("DEF %-45.45s: %s\n",(char *)buf,curhunk);
  221.                                         save_def(fname,curhunk,(char *)buf);
  222.                                         get_and_flush(objfile,1);
  223.                                         break;
  224.                                 case EXT_REF32: /* 32 bit ref */
  225.                                 case EXT_REF16: /* 16 bit ref */
  226.                                 case EXT_REF8:  /*  8 bit ref */
  227.                                 case EXT_DREF32:
  228.                                 case EXT_DREF16:
  229.                                 case EXT_DREF8:
  230.                                         myread(objfile,buf,d1*4);
  231.                                         buf[d1] = 0;
  232.                                         if (pr_ref)
  233.                                                 printf("REF %-45.45s: %s\n",(char *)buf,curhunk);
  234.  
  235.                                         myread(objfile,&d1,sizeof(d1));
  236.                                         get_and_flush(objfile,d1);
  237.                                         break;
  238.                                 case EXT_COMMON:        /* 32 bit ref */
  239.                                         myread(objfile,buf,d1*4);
  240.                                         buf[d1] = 0;
  241.                                         if (pr_def)
  242.                                                 printf("COM %-45.45s: %s\n",(char *)buf,curhunk);
  243.                                         save_def(fname,curhunk,(char *)buf);
  244.  
  245.                                         myread(objfile,&d1,sizeof(d1));
  246.                                         myread(objfile,&d1,sizeof(d1));
  247.                                         get_and_flush(objfile,d1);
  248.                                         break;
  249.                                 default:
  250.                                         printf("ERROR: unknown HUNK_EXT 0x%x\n",d1);
  251.                                 }
  252.                                 myread(objfile,&d1,sizeof(d1));
  253.                         }
  254.                         break;
  255.                         
  256.                 case HUNK_SYMBOL:       /* 3f0  Symbol table info */
  257.                         myread(objfile,&d1,sizeof(d1));
  258.                         while (d1 != 0)
  259.                         {
  260.                                 get_and_flush(objfile,d1+1);
  261.                                 myread(objfile,&d1,sizeof(d1));
  262.                         }
  263.                         break;
  264.                         
  265.                 case HUNK_DEBUG:        /* 3f1  Debug data */
  266.                         myread(objfile,&d1,sizeof(d1));
  267.                         get_and_flush(objfile,d1);
  268.                         break;
  269.                         
  270.                 case HUNK_END:          /* 3f2  End of this hunk */
  271.                         hunkend++;
  272.                         break;
  273.                 case HUNK_HEADER:       /* 3f3  hunk summary info for loader */
  274.                 case HUNK_OVERLAY:      /* 3f5  overlay table info */
  275.                 case HUNK_BREAK:        /* 3f6  end of overlay node */
  276.                 default:
  277.                         printf("ERROR: can't handle hunk 0x%x\n",d1);
  278.                 }
  279.                 
  280.         }
  281.         close(objfile);
  282. }
  283.  
  284. #define MAXEXP 100
  285.  
  286. void
  287. main(argc,argv)
  288. int     argc;
  289. char    *argv[];
  290. {
  291.         int     i,j;
  292.         int     matches;
  293.         char    names[3000];    /* for expanded file names */
  294.         char    *namep[MAXEXP]; /* array for pointers to file names */
  295.         
  296.         /* parse args, set global flags */
  297.  
  298.         if ( argc < 2)
  299.         {
  300.                 printf("usage: %s [-d] [-r] objfile1 ojbfile2 ...\n",argv[0]);
  301.                 exit(1);
  302.         }
  303.         /*
  304.         ** Arg processing, nothing great, but sufficient.       
  305.         */
  306.         for (i = 1 ; i < argc ; i++)
  307.         {
  308.                 if (strcmp(argv[i],"-r") == 0)
  309.                 {
  310.                         pr_ref = 1;
  311.                         continue;
  312.                 }
  313.                 if (strcmp(argv[i],"-d") == 0)
  314.                 {
  315.                         pr_def = 1;
  316.                         continue;
  317.                 }
  318.                 /*
  319.                 ** not an arg, must be an object file. 
  320.                 ** Lattice 3.10 provides the getfnl routine that will take
  321.                 ** an amigados pattern and build a list of matching files.
  322.                 ** It this is not available, the input file name could be
  323.                 ** passed directly to procfile, but the wild card expansion
  324.                 ** is nice.
  325.                 */
  326.                 matches = getfnl(argv[i],names,sizeof(names),0);
  327.                 if (matches > 0)
  328.                 {
  329.                         /* set up pointer array to point to each string */
  330.                         if (strbpl(namep,MAXEXP,names) != matches)
  331.                         {
  332.                                 printf("%s - expansion overflow\n",argv[i]);
  333.                                 continue;
  334.                         }
  335.                         /* sort the pointers, just to be nice */
  336.                         strsrt(namep,matches);
  337.                         
  338.                         /* process the files .... */
  339.                         for ( j = 0 ; j < matches ; j++)
  340.                                 procfile(namep[j]);
  341.                 }
  342.                 else
  343.                 {
  344.                         printf("expansion failed for %s\n",argv[i]);
  345.                 }
  346.         }
  347. }
  348.  
  349. /*
  350. ** build a tree node and call t_insert to put it into the tree of defs.
  351. ** if t_insert returns  0, this is the only definition of the symbol.
  352. ** if t_insert returns -1, there was some unexpected error in t_insert.
  353. ** if t_insert returns anything else, it's a pointer to a node containing
  354. **      the first definiton of the symbol. The current entry is not saved
  355. **      in the tree.
  356. */
  357. void
  358. save_def(fname,hunk,sym)
  359. char    *fname, *hunk, *sym;
  360. {
  361.         /* this routine does the work of building an internal symbol table */
  362.         static T_node t1;
  363.         static T_node *tree = (T_node *)0;
  364.         T_node *rval;
  365.         
  366.         t1.key = sym;
  367.         t1.aux1 = fname;
  368.         t1.aux2 = hunk;
  369.         t1.right = (T_node *)0;
  370.         t1.left  = (T_node *)0;
  371.         rval = t_insert(&tree,&t1);
  372.         if ((int) rval != 0 && (int)rval != -1)
  373.         {
  374.                 printf("%s defined in %s(%s) and %s(%s)\n",
  375.                         sym,rval->aux1,rval->aux2,fname,hunk);
  376.         }
  377. }
  378.  
  379. /*
  380. ** Insert a node into a binary tree. The tree built is never walked so only
  381. ** the insert routine is needed
  382. */
  383. T_node *
  384. t_insert(head,node)
  385. T_node  **head;  /* note double indirection, this simplfies the code later */
  386. T_node  *node;
  387. {
  388.         T_node  *newnode;
  389.         static char *O_aux1 = (char *)0;
  390.         static char *O_aux2 = (char *)0;
  391.         int     result;
  392. #ifdef DEBUG
  393.         printf("key=%s aux1=%s aux2=%s\n",node->key,node->aux1,node->aux2);     
  394. #endif
  395.         /* check for null head pointer, if so create first node */
  396.         if (*head == (T_node *)0)
  397.         {
  398.                 newnode = (T_node *)malloc(sizeof(T_node));
  399.                 if (newnode == (T_node *)0)
  400.                         return((T_node *)-1);
  401.  
  402.                 newnode->key =
  403.                          (char *) malloc(strlen(node->key)+1);
  404.                 strcpy(newnode->key,node->key);
  405.                 
  406.                 newnode->aux1 = O_aux1 = (char *)malloc(strlen(node->aux1)+1);
  407.                 strcpy(newnode->aux1,node->aux1);
  408.  
  409.                 newnode->aux2 = O_aux2 = (char *)malloc(strlen(node->aux2)+1);
  410.                 strcpy(newnode->aux2,node->aux2);
  411. #ifdef DEBUG
  412.                 printf ("newnode =0x%x\n",newnode);
  413. #endif
  414.                 newnode->right = (T_node *)0;
  415.                 newnode->left  = (T_node *)0;
  416.                 *head = newnode;
  417.                 return(0);
  418.         }
  419.         /* walk the tree to find a good spot */
  420.         while (*head != (T_node *)0)
  421.         {
  422. #ifdef DEBUG
  423.                 printf ("TOL: head=0x%x *head=0x%x compare <%s> <%s>\n",
  424.                         head,*head,(*head)->key,node->key);
  425. #endif
  426.                 if ( (result = strcmp((*head)->key,node->key)) == 0)
  427.                 {
  428.                         return(*head);  /* return pointer to dup node */
  429.                 }
  430. #ifdef DEBUG
  431.                 printf ("result=%d\n",result);
  432. #endif
  433.                 if (result >0)
  434.                         head = (T_node **)&(*head)->right;
  435.                 else
  436.                         head = (T_node **)&(*head)->left;
  437.         }
  438. #ifdef DEBUG
  439.         printf ("EOL: head=0x%x *head=0x%x\n",head,*head);
  440. #endif
  441.         /* didn't find it, link it in....
  442.         ** only allocate new space for file and module name if different than
  443.         ** last one remembered, otherwise use the previous string */
  444.         if ( (*head = (T_node *)malloc(sizeof(T_node))) == (T_node *)0)
  445.         {
  446.                 printf("can't allocate space for node!\n");
  447.                 return((T_node *)0);
  448.         }
  449.         (*head)->key = (char *)malloc(strlen(node->key)+1);
  450.         strcpy((*head)->key,node->key);
  451.         
  452.         if (strcmp(node->aux1,O_aux1) == 0)
  453.                 (*head)->aux1 = O_aux1;         /* same thing! */
  454.         else
  455.         {
  456.                 (*head)->aux1 = (char *)malloc(strlen(node->aux1)+1);
  457.                 strcpy((*head)->aux1,node->aux1);
  458.         }
  459.         if (strcmp(node->aux2,O_aux2) == 0)
  460.                 (*head)->aux2 = O_aux2;         /* same thing! */
  461.         else
  462.         {
  463.                 (*head)->aux2 = (char *)malloc(strlen(node->aux2)+1);
  464.                 strcpy((*head)->aux2,node->aux2);
  465.         }
  466.         (*head)->right = (T_node *)0;
  467.         (*head)->left  = (T_node *)0;
  468.         return((T_node *)0);
  469. }
  470. r array to point to each string */
  471.                         if (strbpl(namep,MAXEXP